<?php

/**
 * Name: 值班管理请求验证类
 * User: Silent
 * Date: 2025-11-07
 * Time: 17:00:00
 */

namespace App\Http\Requests\Checkin;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Contracts\Validation\Validator;

class DutyRequest extends FormRequest
{
    /**
     * 判断用户是否有权限进行此请求
     */
    public function authorize()
    {
        return true;
    }

    /**
     * 获取验证规则
     */
    public function rules()
    {
        $rules = [];
        $routeName = $this->route()->getName();

        // 根据不同的请求类型设置不同的验证规则
        if (str_contains($routeName, 'leader')) {
            // 当班班长设置
            $rules = $this->getLeaderRules();
        } elseif (str_contains($routeName, 'supervisor')) {
            // 值班领导设置
            $rules = $this->getSupervisorRules();
        }

        // 通用日期验证
        if ($this->has('date')) {
            $rules['date'] = 'required|date_format:Y-m-d|after_or_equal:today';
        }

        return $rules;
    }

    /**
     * 获取当班班长验证规则
     */
    private function getLeaderRules()
    {
        // 检查是单个设置还是批量设置
        if ($this->has('leader_id')) {
            // 单个设置
            return [
                'leader_id' => 'required|integer|exists:employees,id',
                'team_name' => 'nullable|string|max:255',
            ];
        } else {
            // 批量设置
            return [
                '*.leader_id' => 'required|integer|exists:employees,id',
                '*.team_name' => 'required|string|max:255',
            ];
        }
    }

    /**
     * 获取值班领导验证规则
     */
    private function getSupervisorRules()
    {
        return [
            'supervisor_id' => 'required|integer|exists:employees,id',
            'phone' => 'nullable|string|max:20|regex:/^1[3-9]\d{9}$/',
            'location' => 'nullable|string|max:255',
            'time_range' => 'nullable|string|max:100',
            'remark' => 'nullable|string|max:500',
        ];
    }

    /**
     * 获取验证错误消息
     */
    public function messages()
    {
        return [
            // 当班班长验证消息
            'leader_id.required' => '请选择当班班长',
            'leader_id.integer' => '班长ID格式错误',
            'leader_id.exists' => '选择的班长不存在',
            'team_name.string' => '班组名称格式错误',
            'team_name.max' => '班组名称不能超过255个字符',

            // 批量设置验证消息
            '*.leader_id.required' => '请选择当班班长',
            '*.leader_id.integer' => '班长ID格式错误',
            '*.leader_id.exists' => '选择的班长不存在',
            '*.team_name.required' => '请填写班组名称',
            '*.team_name.string' => '班组名称格式错误',
            '*.team_name.max' => '班组名称不能超过255个字符',

            // 值班领导验证消息
            'supervisor_id.required' => '请选择值班领导',
            'supervisor_id.integer' => '领导ID格式错误',
            'supervisor_id.exists' => '选择的领导不存在',
            'phone.string' => '联系电话格式错误',
            'phone.max' => '联系电话不能超过20个字符',
            'phone.regex' => '请输入正确的手机号码格式',
            'location.string' => '值班地点格式错误',
            'location.max' => '值班地点不能超过255个字符',
            'time_range.string' => '值班时间段格式错误',
            'time_range.max' => '值班时间段不能超过100个字符',
            'remark.string' => '备注格式错误',
            'remark.max' => '备注不能超过500个字符',

            // 通用日期验证消息
            'date.required' => '请选择值班日期',
            'date.date_format' => '日期格式错误，请使用YYYY-MM-DD格式',
            'date.after_or_equal' => '值班日期不能是过去的日期',
        ];
    }

    /**
     * 获取字段别名
     */
    public function attributes()
    {
        return [
            'leader_id' => '当班班长',
            'team_name' => '班组名称',
            'supervisor_id' => '值班领导',
            'phone' => '联系电话',
            'location' => '值班地点',
            'time_range' => '值班时间段',
            'remark' => '备注说明',
            'date' => '值班日期',
        ];
    }

    /**
     * 自定义验证逻辑
     */
    public function withValidator(Validator $validator)
    {
        $validator->after(function (Validator $validator) {
            $routeName = $this->route()->getName();

            if (str_contains($routeName, 'leader')) {
                $this->validateLeaderRequest($validator);
            } elseif (str_contains($routeName, 'supervisor')) {
                $this->validateSupervisorRequest($validator);
            }
        });
    }

    /**
     * 验证当班班长请求
     */
    private function validateLeaderRequest(Validator $validator)
    {
        // 如果是批量设置，检查是否有重复的班组
        if (is_array($this->input()) && !$this->has('leader_id')) {
            $teams = array_column($this->input(), 'team_name');
            if (count($teams) !== count(array_unique($teams))) {
                $validator->errors()->add('team_name', '不能为同一个班组设置多个当班班长');
            }
        }

        // 验证日期不能是过去的日期（当天可以）
        if ($this->has('date')) {
            $date = $this->input('date');
            if ($date && strtotime($date) < strtotime(today())) {
                $validator->errors()->add('date', '不能设置过去日期的当班班长');
            }
        }
    }

    /**
     * 验证值班领导请求
     */
    private function validateSupervisorRequest(Validator $validator)
    {
        // 验证时间段格式
        $timeRange = $this->input('time_range');
        if ($timeRange) {
            // 简单验证时间段格式，例如：08:00-18:00
            if (!preg_match('/^\d{1,2}:\d{2}-\d{1,2}:\d{2}$/', $timeRange)) {
                $validator->errors()->add('time_range', '时间段格式错误，请使用HH:MM-HH:MM格式');
            }
        }

        // 验证值班地点不能包含特殊字符
        $location = $this->input('location');
        if ($location && preg_match('/[<>\"\'&]/', $location)) {
            $validator->errors()->add('location', '值班地点不能包含特殊字符');
        }
    }

    /**
     * 处理验证失败
     */
    protected function failedValidation(Validator $validator)
    {
        $errors = $validator->errors()->toArray();

        // 格式化错误消息
        $formattedErrors = [];
        foreach ($errors as $field => $messages) {
            $formattedErrors[$field] = $messages[0]; // 只取第一个错误消息
        }

        $response = response()->json([
            'code' => 422,
            'message' => '值班设置数据验证失败',
            'data' => null,
            'errors' => $formattedErrors
        ], 422);

        throw new HttpResponseException($response);
    }

    /**
     * 获取处理后的验证数据
     */
    public function getProcessedData()
    {
        $data = $this->validated();

        // 清理字符串字段的空格
        $stringFields = ['team_name', 'phone', 'location', 'time_range', 'remark'];
        foreach ($stringFields as $field) {
            if (isset($data[$field]) && is_string($data[$field])) {
                $data[$field] = trim($data[$field]);
                // 如果清理后为空字符串，设置为null
                if ($data[$field] === '') {
                    $data[$field] = null;
                }
            }
        }

        return $data;
    }

    /**
     * 检查是否为批量设置
     */
    public function isBatchSetting()
    {
        return is_array($this->input()) && !$this->has('leader_id') && !$this->has('supervisor_id');
    }

    /**
     * 获取设置类型
     */
    public function getDutyType()
    {
        $routeName = $this->route()->getName();

        if (str_contains($routeName, 'leader')) {
            return 'leader';
        } elseif (str_contains($routeName, 'supervisor')) {
            return 'supervisor';
        }

        return 'unknown';
    }
}
